#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UTable.Input.MultiTouch;
using System.Windows;
using UTable.Objects.Controls;

namespace UTable.Objects.Handlers
{
	public class SingleFingerHandler : MultiTouchEventHandlerClass
	{
		#region Private Fields

		private int _currentFingerId = -1;

		private IInputNode _node;

		#endregion

		#region Properties

		public int CurrentFingerId { get { return _currentFingerId; } }

        /// <summary>
        /// The current control this handler is attached
        /// </summary>
		public IInputNode Node { get { return _node; } }

        /// <summary>
        /// Indicate whether the handler should capture the finger
        /// The default value is true
        /// </summary>
		public Boolean CaptureFinger { get; set; }

        /// <summary>
        /// Indicate whether the handler should capture the finger in second way. 
        /// That is,  capture the finger by using UTableHelper.CaptureFinger2
        /// The default value is false
        /// </summary>
        public Boolean CaptureFinger2 { get; set; }

        /// <summary>
        /// Indicate whether all the inputs handled by this handler should be marked as handled
        /// The default value is true
        /// </summary>
		public Boolean HandleAllEvents { get; set; }

        /// <summary>
        /// Indicate whether all the inputs handled by this handler should be routed down to its parent node
        /// The default value is true
        /// </summary>
		public Boolean StopRouteDown { get; set; }

		#endregion

        #region Constructors

        public SingleFingerHandler(IInputNode node)
		{
			_node = node;
			CaptureFinger = true;
			HandleAllEvents = true;
			StopRouteDown = true;
            CaptureFinger2 = false;
		}

		#endregion

        #region Public Methods

        public override void OnMultiTouch(MultiTouchEventArgs args)
        {
            foreach (FingerEventArgs fargs in args.FingerEvents)
            {
                switch (fargs.EventType)
                {
                    case FingerEventType.FINGER_DOWN_EVENT:
                        OnContactDown(fargs);
                        break;
                    case FingerEventType.FINGER_MOVE_EVENT:
                        OnContactMove(fargs);
                        break;
                    case FingerEventType.FINGER_UP_EVENT:
                        OnContactUp(fargs);
                        break;
                    case FingerEventType.FINGER_OUT_EVENT:
                        OnContactLeave(fargs);
                        break;
                    case FingerEventType.FINGER_IN_EVENT:
                        OnContactEnter(fargs);
                        break;
                }
            }
            if (HandleAllEvents)
                args.Handled = true;
            if (StopRouteDown)
                args.RouteDown = false;
        }

        #endregion

		#region Private Methods

		private void OnContactDown(FingerEventArgs args)
		{
			if (_currentFingerId >= 0)
				return;
            if (CaptureFinger)
                _node.CaptureFinger(args.FingerID);
            else if (CaptureFinger2)
                UTableHelper.CaptureFinger2(_node as IVisualNode, args.FingerID);
			_currentFingerId = args.FingerID;
			args.Handled = true;
			OnSingleFingerDown(args);
			if (SingleFingerDown != null)
				SingleFingerDown(this, args);
		}

		private void OnContactMove(FingerEventArgs args)
		{
			if (_currentFingerId != args.FingerID)
				return;
			args.Handled = true;
			OnSingleFingerMove(args);
			if (SingleFingerMove != null)
				SingleFingerMove(this, args);
		}

		private void OnContactUp(FingerEventArgs args)
		{
			if (args.FingerID == _currentFingerId)
			{
				Point p = args.Position;
				_currentFingerId = -1;
				if (CaptureFinger)
					_node.UncaptureFinger(args.FingerID);
                else if (CaptureFinger2)
                    UTableHelper.UncaptureFinger2(_node as IVisualNode, args.FingerID);
				args.Handled = true;
				OnSingleFingerUp(args);
				if (SingleFingerUp != null)
					SingleFingerUp(this, args);
			}
		}

        private void OnContactEnter(FingerEventArgs args)
        {
            if (_currentFingerId >= 0)
                return;
            if (!CaptureFinger && !CaptureFinger2)
            {
                _currentFingerId = args.FingerID;
            }
            args.Handled = true;
            if (SingleFingerEnter != null)
                SingleFingerEnter(this, args);
        }

        private void OnContactLeave(FingerEventArgs args)
        {
            if (args.FingerID == _currentFingerId)
            {
                if (!CaptureFinger && !CaptureFinger2)
                {
                    _currentFingerId = -1;
                }
                args.Handled = true;
                if (SingleFingerLeave != null)
                    SingleFingerLeave(this, args);
            }
        }

		#endregion

		#region Protected Methods

		protected virtual void OnSingleFingerDown(FingerEventArgs fArgs)
		{

		}

		protected virtual void OnSingleFingerMove(FingerEventArgs fArgs)
		{

		}

		protected virtual void OnSingleFingerUp(FingerEventArgs fArgs)
		{

		}

		#endregion

		#region Events

		public event SingleFingerEventHandler SingleFingerDown;

		public event SingleFingerEventHandler SingleFingerMove;

		public event SingleFingerEventHandler SingleFingerUp;

        public event SingleFingerEventHandler SingleFingerEnter;

        public event SingleFingerEventHandler SingleFingerLeave;

		#endregion
	}

	public delegate void SingleFingerEventHandler(SingleFingerHandler sender, FingerEventArgs args);
}
